package com.xzq.erp.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * 配置类，注册web层相关组件
 */
@Configuration
@Slf4j
@EnableAsync
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Autowired
    @Qualifier("JacksonObjectMapper")
    private ObjectMapper objectMapper;

    /**
     * 设置静态资源映射
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始进行静态资源映射...");
        // 静态资源
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        
        // Knife4j和SpringDoc需要的静态资源
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/webjars/swagger-ui/");
        registry.addResourceHandler("/v3/api-docs/**").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/swagger-resources/**").addResourceLocations("classpath:/META-INF/resources/swagger-resources/");
    }
    
    /**
     * 配置视图控制器，设置一些特殊请求的跳转
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 设置主页
        registry.addRedirectViewController("/", "/doc.html");
        // 设置Swagger UI
        registry.addRedirectViewController("/swagger-ui", "/swagger-ui.html");
    }

    /**
     * 扩展SpringMVC的消息转换器(实现对日期统一转换)
     * @param converters
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 创建消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        // 需要指定一个对象转换器 将Java对象转换为json
        converter.setObjectMapper(objectMapper);
        // 将消息转换器对象追加到mvc框架的转换器集合中
        converters.add(converters.size()-1, converter);
    }

    /**
     * 配置异步请求支持
     * @param configurer
     */
    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        configurer.setTaskExecutor(asyncTaskExecutor());
        // 设置超时时间（可选）
        configurer.setDefaultTimeout(30000); // 30秒
    }

    /**
     * 创建异步任务执行器
     * @return
     */
    @Bean
    public AsyncTaskExecutor asyncTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);         // 核心线程数
        executor.setMaxPoolSize(10);         // 最大线程数
        executor.setQueueCapacity(100);      // 队列容量
        executor.setThreadNamePrefix("Async-"); // 线程名前缀
        executor.initialize();
        return executor;
    }
}
